package com.ywx.yypicturebackend.manager.upload;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.RandomUtil;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.ciModel.persistence.CIObject;
import com.qcloud.cos.model.ciModel.persistence.ImageInfo;
import com.qcloud.cos.model.ciModel.persistence.ProcessResults;
import com.ywx.yypicturebackend.config.CosClientConfig;
import com.ywx.yypicturebackend.exception.BusinessException;
import com.ywx.yypicturebackend.exception.ErrorCode;
import com.ywx.yypicturebackend.manager.CosManager;
import com.ywx.yypicturebackend.model.dto.file.UploadPictureResult;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.List;

/**
 * 模板类
 * 与业务有关的公共文件处理方法
 */
@Slf4j
public abstract class PictureUploadTemplate {

    @Resource
    CosClientConfig cosClientConfig;

    @Resource
    CosManager cosManager;


    /**
     * 上传图片模板方法
     *
     * @param inputSource      输入源(文件或URL等)
     * @param uploadPathPrefix 上传路径前缀
     * @return
     */
    public UploadPictureResult uploadPicture(Object inputSource, String uploadPathPrefix) {

        //1.校验图片
        validPicture(inputSource);

        //2.图片上传地址
        String uuid = RandomUtil.randomString(6);

        String originalFilename = getOriginalFilename(inputSource);

        String uploadFileName = String.format("%s_%s.%s", DateUtil.formatDate(new Date()),
                uuid, FileUtil.getSuffix(originalFilename));
        String uploadPath = String.format("/%s/%s", uploadPathPrefix, uploadFileName);
        //创建临时文件
        File file = null;

        try {
            file = File.createTempFile(uploadPath, null);
            //将文件内容拷贝到临时文件中
            processFile(inputSource, file);
            //上传图片
            PutObjectResult putObjectResult = cosManager.putPictureObject(uploadPath, file);

            //获取图片信息
            ImageInfo imageInfo = putObjectResult.getCiUploadResult().getOriginalInfo().getImageInfo();

            //获取到图片处理结果
            ProcessResults processResults = putObjectResult.getCiUploadResult().getProcessResults();
            List<CIObject> objectList = processResults.getObjectList();

            if (CollUtil.isNotEmpty(objectList)) {
                //拿到.webp文件
                CIObject compressedCiObject = objectList.get(0);
                //缩略图默认是压缩图
                CIObject thumbnailCiObject = compressedCiObject;
                //如果有缩略图
                if (objectList.size() > 1) {
                    //拿到缩略图
                    thumbnailCiObject = objectList.get(1);
                }
                //返回缩略图封装结果
                return buildResult(originalFilename, compressedCiObject, thumbnailCiObject, uploadPath, imageInfo);
            }

            //返回原图封装结果
            return buildResult(originalFilename, uploadPath, file, imageInfo);
        } catch (Exception e) {
            log.error("图片上传到对象存储失败", e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "文件上传失败");
        } finally {
            //3.删除临时文件
            this.deleteTempFile(file);
        }
    }

    /**
     * 上传文件到对象存储,返回 封装好的对象存储返回结果(带缩略图)
     * @param originalFilename   原始文件名
     * @param compressedCiObject 返回的缩略图文件对象
     * @param thumbnailCiObject
     * @param uploadPath
     * @return
     */
    private UploadPictureResult buildResult(String originalFilename, CIObject compressedCiObject, CIObject thumbnailCiObject, String uploadPath,ImageInfo imageInfo) {
        UploadPictureResult uploadPictureResult = new UploadPictureResult();

        Integer picWidth = compressedCiObject.getWidth();
        Integer picHeight = compressedCiObject.getHeight();

        double picScale = NumberUtil.round(1.0 * picWidth / picHeight, 2).doubleValue();

        uploadPictureResult.setPicName(FileUtil.mainName(originalFilename));
        uploadPictureResult.setPicSize(compressedCiObject.getSize().longValue());
        uploadPictureResult.setPicWidth(picWidth);
        uploadPictureResult.setPicHeight(picHeight);
        uploadPictureResult.setPicScale(picScale);
        uploadPictureResult.setPicFormat(compressedCiObject.getFormat());
        uploadPictureResult.setUrl(cosClientConfig.getHost() + "/" + compressedCiObject.getKey());//这里设置的是压缩图(.webp)路径
//        https://ywx-picture-1358972076.cos.ap-guangzhou.myqcloud.com//public/1/2025-05-18_JvqW0a.jpg
        //设置缩略图路径
        uploadPictureResult.setThumbnailUrl(cosClientConfig.getHost() + "/" + thumbnailCiObject.getKey());

        //设置原图路径
        uploadPictureResult.setOriginalUrl(cosClientConfig.getHost() + uploadPath);

        //设置图片颜色
        uploadPictureResult.setPicColor(imageInfo.getAve());

        return uploadPictureResult;
    }


    /**
     * 上传文件到对象存储,返回 封装好的对象存储返回结果(原图)
     *
     * @param originalFilename
     * @param uploadPath
     * @param file
     * @param imageInfo
     * @return
     */
    private UploadPictureResult buildResult(String originalFilename, String uploadPath, File file, ImageInfo imageInfo) {
        UploadPictureResult uploadPictureResult = new UploadPictureResult();

        int picWidth = imageInfo.getWidth();
        int picHeight = imageInfo.getHeight();
        //计算宽高比
        double picScale = NumberUtil.round(picWidth * 1.0 / picHeight, 2).doubleValue();

        uploadPictureResult.setUrl(cosClientConfig.getHost() + uploadPath);
        uploadPictureResult.setPicName(FileUtil.mainName(originalFilename));
        uploadPictureResult.setPicSize(FileUtil.size(file));
        uploadPictureResult.setPicWidth(picWidth);
        uploadPictureResult.setPicHeight(picHeight);
        uploadPictureResult.setPicScale(picScale);
        uploadPictureResult.setPicFormat(imageInfo.getFormat());
        uploadPictureResult.setPicColor(imageInfo.getAve());
        return uploadPictureResult;
    }

    /**
     * 处理文件来源,将文件内容拷贝到临时文件中
     *
     * @param inputSource
     * @param file
     */
    protected abstract void processFile(Object inputSource, File file) throws IOException;

    /**
     * 获取文件名
     *
     * @param inputSource
     * @return
     */
    protected abstract String getOriginalFilename(Object inputSource);

    /**
     * 校验图片
     *
     * @param inputSource 输入源
     */
    protected abstract void validPicture(Object inputSource);


    /**
     * 删除临时文件
     */
    public void deleteTempFile(File file) {
        if (file == null) {
            return;
        }
        // 删除临时文件
        boolean deleteResult = file.delete();
        if (!deleteResult) {
            log.error("file delete error, filepath = {}", file.getAbsolutePath());
        }
    }


}
